package com.frontier.gateway8000.predicate;

import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.cloud.gateway.handler.predicate.AbstractRoutePredicateFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;

import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Predicate;

/**
 * 自定义断言规则，满足/xx/**，并且不在黑名单中的请求路由，
 *
 * @author YLS-XuXu
 * @date 2022/3/3
 */
@Component
public class RequestRateLimiterRoutePredicateFactory extends AbstractRoutePredicateFactory<RequestRateLimiterRoutePredicateFactory.Config> {

   /**
    * 将自定义配置加载父类（父类做了读取配置文件的处理）
    */
    public RequestRateLimiterRoutePredicateFactory() {
        super(RequestRateLimiterRoutePredicateFactory.Config.class);
    }

   /**
    * 将配置文件中的值按返回集合的顺序，赋值给配置类
    */
    @Override
    public List<String> shortcutFieldOrder() {
        return Arrays.asList(new String[]{"path", "pathBlackList"});
    }

    @Override
    public Predicate<ServerWebExchange> apply(Consumer<Config> consumer) {
        return super.apply(consumer);
    }

    @Override
    public Predicate<ServerWebExchange> apply(Config config) {
        // 创建网关断言对象
        return new Predicate<ServerWebExchange>() {
            // 检查
            @Override
            public boolean test(ServerWebExchange serverWebExchange) {
                String urlPath=serverWebExchange.getRequest().getPath().pathWithinApplication().value();
                boolean predicateResult = false;
                String pathPrefix = config.path.substring(0, config.path.indexOf("/**"));
                //路径以指定path为前缀
                if(urlPath.startsWith(pathPrefix)){
                    predicateResult=true;
                }
                if(urlPath.contains(config.pathBlackList)){
                    predicateResult=false;
                }
                return predicateResult;
            }
        };
    }

    /**
     * 断言内部配置类
     */
    @Data
    @NoArgsConstructor
    public static class Config {
        // 请求路径
        private String path;
        // 路径黑名单
        private String pathBlackList;
    }
}
